package account.controller;


import account.entity.Account;
import account.service.IAccountService;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author lh
 * @since 2020-08-08
 */
@RestController
@RequestMapping
@Slf4j
public class AccountController {
    @Autowired
    private IAccountService accountService;

    @SentinelResource(value = "getByCode", blockHandler = "handleException")
    @GetMapping("/account/{accountCode}")
    public Account getByCode(@PathVariable String accountCode) {
        log.info("get account detail,accountCode is :{}", accountCode);
        QueryWrapper<Account> wrapper = new QueryWrapper();
        wrapper.lambda().eq(Account::getAccountCode, accountCode);
        return accountService.getOne(wrapper);
    }

    @SentinelResource(value = "fallbackTest", fallback = "fallbackHandler")
    @PostMapping("/fallback/{accountCode}")
    public void fallback(@RequestBody Account account) {
        throw new RuntimeException("运行错误了");
    }

    @PostMapping("/account/update")
    public boolean update(Account Account) {
        log.info("update account:{}", Account);
        return accountService.updateById(Account);
    }

    @PostMapping("/account/insert")
    public boolean insert(Account Account) {
        log.info("insert account:{}", Account);
        return accountService.save(Account);
    }

    @PostMapping("/account/delete")
    public boolean delete(@RequestParam String accountCode) {
        log.info("delete account,accountCode is {}", accountCode);
        QueryWrapper<Account> wrapper = new QueryWrapper();
        wrapper.lambda().eq(Account::getAccountCode, accountCode);
        return accountService.remove(wrapper);
    }

    @PostMapping("/account/reduce")
    public boolean reduce(String accountCode, BigDecimal amount) {
        log.info("account reduce:{},{}", accountCode,amount);
        QueryWrapper<Account> wrapper = new QueryWrapper();
        wrapper.lambda().eq(Account::getAccountCode, accountCode);
        Account account = accountService.getOne(wrapper);
        account.setAmount(account.getAmount().subtract(amount));
        return accountService.updateById(account);
    }

    /**
     * 自定义异常策略
     * 返回值和参数要跟目标函数一样，参数可以追加BlockException
     */
    public Account handleException(String accountCode, BlockException exception) {
        log.info("达到阈值了,不要再访问了!,{}", exception.getClass().getCanonicalName());
        return null;
    }

    public void fallbackHandler(Account account) {
        log.info("熔断了,服务错误，触发熔断");
    }
}
